#pragma once
//============================================================================
// Copyright (C) 2010-2013 Brett R. Jones
//
// Issued to public domain 2010
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================

//=== cheezy crypto with known weeknesses ===//

//TEMPORARY UNTIL REPLACE CHEEZY CRYPT WITH BETTER
#define CheezyKey		VxKey
#define CheezyCrypt		VxCrypto

//! macro returns true if length is a multiple of 16 and encryptable by tronacom
//! NOTE: see macro ROUND_TO_16BYTE_BOUNDRY for handy way to round length up to a multiple of 16 bytes
#define VxIsEncryptable( exp )	((((exp) & 0xf )||(0==(exp)))?0:1)

#define		CHEEZY_CHALLENGE_LEN	16
#define		CHEEZY_SYM_KEY_LEN		16		// length of symetric key
#define		CHEEZY_KNOWN_TEXT_STR	"1)!@#JV*K%^#&f|" // known string 16 chars long


#include "Blowfish.h"
class CheezyKey
{
public:
	//=== constructor ===//
	CheezyKey();
	//=== destructor ===//
	~CheezyKey();

	//! return true if key has been set
	BOOL	IsKeySet( void ){ return m_bIsSet;}
	//! get key length in bytes
	int		GetKeyLength( void ) { return 16; }
	//! validate is a valid length to encrypt or decrypt
	BOOL	IsValidDataLen( int iDataLen ){ return (iDataLen & 0x0f)?0:1; }

	//! set key from data..
	RCODE	ImportKey( unsigned char * pu8Data, int iLen );
	//! set encryption key from another
	void	ImportKey( VxKey * poKey );
	//! return key into data buffer
	RCODE	ExportKey( unsigned char * pu8RetKeyData, int iBufLen );
	//! export encryption key to another another
	void	ExportKey( VxKey * poKey );
	//! make encryption key from password
	RCODE	SetKeyFromPassword( const char *	pPassword,			// password
								int				iPasswordLen,		// length of password
								const char *	pSalt = "p9@g");	// salt
	//! make encryption key from user name and password 
	RCODE	SetKeyFromPassword( const char *	pUserName,			// user name
								const char *	pPassword,			// password
								const char *	pSalt = "$x*2");	// salt

	//=== vars ===//
	U32			m_au32Key[ CHEEZY_SYM_KEY_LEN / sizeof(U32) ];
	U8			m_bIsSet;		// true if key has been set	
};
class CheezyCrypt
{
public:
	//=== constructor ===//
	CheezyCrypt();

	//! return true if key set and context generated
	BOOL IsKeyValid( void ){ return m_bIsKeyValid; }

	//! set key used for encryption and decryption
	void			SetKey( CheezyKey * poKey ) { ImportKey( poKey ); }

	//! get key used for encryption and decryption
	CheezyKey *		GetKey( void ){ return &m_oKey;}

	//! set key used for encryption and decryption
	RCODE			ImportKey( CheezyKey * poKey );

	//! generate key from password and set encryption key in one fuction call
	//! NOTE: Max password len 255
	RCODE			SetPassword( const char * pPassword, int iPasswordLen );

	//! Generate encryption key from password
	RCODE			GenerateKey( const char * pPassword, int iPasswordLen, CheezyKey * pgRetKey );

	//! Encrypt some data
	//! NOTE: iDataLen must be a multiple of 16
	RCODE			Encrypt( unsigned char * pu8Data, int iDataLen );

	//! Decrypt some data
	//! NOTE: iDataLen must be a multiple of 16
	RCODE			Decrypt( unsigned char * pu8Data, int iDataLen );

	//! encrypt known string
	RCODE			EncryptKnownString( unsigned char * pu8RetData, int iDataLen );

	//! verify data is known text string
	RCODE			VerifyKnownString( unsigned char * pu8Data, int iDataLen );

	//=== vars ===//
	BlowCtx		m_oBlowCtx;			// context of blowfish
	CheezyKey	m_oKey;				// encryption key
	BOOL		m_bIsKeyValid;		// if true encryption key has been set
};

//---------------------------------------------------------------------------
// global functions
//---------------------------------------------------------------------------
//! fill with random data
//! NOTE: this is not truly random enough for strong encryption uses
void CheezyFillRandom( void * pvData, int iLen );

//---------------------------------------------------------------------------
//! Encrypt data with CheezyCrypto
RCODE VxSymEncrypt(		CheezyKey *		poKey,			// Symmetric key must be 16 bytes long
						char *			pData,			// buffer to encrypt
						int				iDataLen,		// data length ( must be multiple of key length )
						char *			pRetBuf = 0 );	// if null then encrypted data put in pData
//---------------------------------------------------------------------------
//! Decrypt data with CheezyCrypto
RCODE VxSymDecrypt(		CheezyKey *		poKey,			// Symmetric key must be 16 bytes long
						char *			pData,			// buffer to decrypt
						int				iDataLen,		// data length ( must be multiple of key length )
						char *			pRetBuf = 0 );	// if null then encrypted data put in pData
